package com.siwei.mes.sync.erp.service.impl;

import com.siwei.mes.common.util.ConvertUtils;
import com.siwei.mes.common.util.JsonUtils;
import com.siwei.mes.entity.erp.Itemorder;
import com.siwei.mes.entity.erp.Rwdextra;
import com.siwei.mes.entity.erp.RwdextraInfo;
import com.siwei.mes.entity.experiment.*;
import com.siwei.mes.entity.experiment.concrete.batch.ConcreteKzqd;
import com.siwei.mes.entity.mixproportion.MixProportion;
import com.siwei.mes.entity.system.TestProjectInfo;
import com.siwei.mes.enums.*;
import com.siwei.mes.mapper.experiment.*;
import com.siwei.mes.mapper.mixProportion.MixProportionMapper;
import com.siwei.mes.service.experiment.ExperimentDetailService;
import com.siwei.mes.service.experiment.ExperimentService;
import com.siwei.mes.sync.erp.service.GenConcreteService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 生成抗折试验委托
 *
 * @Description: 生成抗折试验委托
 * @Version: 1.0
 * @author: mlchen
 * @date: 2025/1/8 16:43
 */
@Service
public class GenKzExperimentService extends GenConcreteService {
    private static final Logger log = LoggerFactory.getLogger("erp");
    @Resource
    private ExperimentGenConfigMapper experimentGenConfigMapper;
    @Resource
    private ExperimentService experimentService;
    @Resource
    private ExperimentMapper experimentMapper;
    @Resource
    private ExperimentDetailMapper experimentDetailMapper;
    @Resource
    private ExperimentSampleSmokeMapper experimentSampleSmokeMapper;
    @Resource
    private ExperimentCheckItemorderMapper experimentCheckItemorderMapper;
    @Resource
    private MixProportionMapper mixProportionMapper;
    @Resource
    private ExperimentDetailService experimentDetailService;

    /**
     * 生成抗折强度
     *
     * @param rwdextra           任务单
     * @param itemorder          小票
     * @param testProjectInfoMap 试验项目map
     * @return
     */
    public Long genExperiment(Rwdextra rwdextra, Itemorder itemorder, Map<String, TestProjectInfo> testProjectInfoMap) {
        try {
            log.info("生成混凝土抗折强度开始，任务单号：【{}】，小票id；【{}】", rwdextra.getFrwdh(), itemorder.getItid());
            RwdextraInfo rwdextraInfo = rwdextra.getRwdextraInfo();
            if (rwdextraInfo == null) {
                log.info("混凝土抗折强度生成委托对应任务单扩展信息为空，暂不生成，任务单：【{}】，小票id：【{}】", rwdextra.getFrwdh(), itemorder.getItid());
                return null;
            }
            String fPhbNo = rwdextra.getPhbshow();
            String tpz = itemorder.getTpz();
            String fGcmc = rwdextraInfo.getFGcmc();
            Integer frwdh = rwdextra.getFrwdh();

            if (StringUtils.isBlank(fPhbNo)) {
                log.info("混凝土抗折强度对应任务单没有配合比编号，暂不生成，任务单：【{}】，小票id：【{}】", rwdextra.getFrwdh(), itemorder.getItid());
                return null;
            }
            if (StringUtils.isBlank(tpz)) {
                log.info("混凝土抗折强度对应砼品种为空，暂不生成，任务单：【{}】，小票id：【{}】", rwdextra.getFrwdh(), itemorder.getItid());
                return null;
            }

            String mesTpzToKz = ConvertUtils.getMesTpzToKz(tpz);
            if (StringUtils.isBlank(mesTpzToKz)) {
                log.info("混凝土抗折强度对应抗折要求为空，暂不生成，砼品种：【{}】，任务单：【{}】，小票id：【{}】", tpz, rwdextra.getFrwdh(), itemorder.getItid());
                return null;
            }
            log.info("混凝土抗折强度对应的砼品种为：【{}】，抗折要求：【{}】", tpz, mesTpzToKz);
            log.info("开始组装混凝土【抗折强度】对应试验委托，抗折要求：【{}】，配合比号：【{}】,砼品种：【{}】，工程名称：【{}】，任务单号：【{}】，小票id：：【{}】",
                    mesTpzToKz, fPhbNo, tpz, fGcmc, rwdextra.getFrwdh(), itemorder.getItid());
            ExperimentGenConfig config = experimentGenConfigMapper.selectOne(new ExperimentGenConfig().setCheckType(CheckEnum.BATCH.getCode())
                    .setTestCode(TestProjectEnum.CONCRETE_PARAM_KZQD.getCode()).setExperimentType(MaterialsEnum.CONCRETE.getCode()));

            if (config == null) {
                log.info("混凝土抗折强度生成委托规则配置为空，暂不生成，任务单：【{}】，小票id：【{}】", rwdextra.getFrwdh(), itemorder.getItid());
                return null;
            }
            if (config.getIsOpen() == null || config.getIsOpen() == 0) {
                log.info("混凝土抗折强度生成委托规则配置暂未开启，暂不生成！任务单：【{}】，小票id：【{}】", rwdextra.getFrwdh(), itemorder.getItid());
                return null;
            }

            TestProjectInfo projectInfo = testProjectInfoMap.get(TestProjectEnum.CONCRETE_PARAM_KZQD.getCode());
            if (projectInfo == null) {
                log.info("混凝土抗折强度对应试验项目配置未配置，暂不生成！任务单：【{}】，小票id：【{}】", rwdextra.getFrwdh(), itemorder.getItid());
                return null;
            }

            /**委托试验名称*/
            Set<String> entrustExperimentSet = new HashSet<>();
            /**试验项目code集合*/
            Set<String> testProjectCodeList = new HashSet<>();
            testProjectCodeList.add(projectInfo.getTestCode());
            entrustExperimentSet.add(projectInfo.getTestName());

            /**获取所有试验项目配置*/
            List<TestProjectInfo> testProjectInfoList = new ArrayList<>();
            testProjectInfoList.add(projectInfo);

            Long experimentId = null;

            /**批检与试验台账和小票的关系*/
            List<ExperimentCheckItemorder> needAddCheckItemorderList = new ArrayList<>();

            Integer checkRules = config.getCheckRules();//规则 1-车车都检  2-按重量  3-按车数  4-按时间
            if (checkRules == null) {
                log.info("混凝土抗折生成规则为空直接跳过。");
                return null;
            }
            String checkThreshold = config.getCheckThreshold() == null ? "0" : config.getCheckThreshold();//阈值  多少吨或者多少天  根据规则来走的
            Integer qualifiedType = config.getQualifiedType();//限定类型  1-同一厂家（同一配合比）   2-同一批次（同一任务单）
            /**任务单只有1-车车都检  2-按重量  3-按车数  没有 4-按时间 */
            if (checkRules == 1) {//车车都检
                experimentId = null;
            } else if (checkRules == 2 || checkRules == 3) {//2-按重量  3-按车数
                log.info("混凝土抗折强度按重量或者按车数判断开始！");
                /**查询对应批检检是否有之前的台账关联关系*/
                ExperimentCheckItemorder checkItemorder = new ExperimentCheckItemorder()
                        .setCheckType(CheckEnum.BATCH.getCode()).setTestCode(projectInfo.getTestCode()).setTestName(projectInfo.getTestName());
                if (qualifiedType != null && qualifiedType == 1) {//1-同一厂家（同一配合比）
                    checkItemorder.setPhb(fPhbNo);
                } else if (qualifiedType != null && qualifiedType == 2) {//2-同一工程
                    checkItemorder.setGcmc(fGcmc);
                }
                log.info("查询之前小票对应试验委托关系入参：【{}】", JsonUtils.getJson(checkItemorder));
                List<ExperimentCheckItemorder> checkList = experimentCheckItemorderMapper.getList(checkItemorder);
                log.info("之前小票对应的试验委托关系，查询条数：【{}】", checkList.size());

                double totalThreshold = 0;// 之前的条数或者是方量
                double addTotal = 0;// 本次加上之前的条数或者方量

                if (checkRules == 3) {//3-按车数 就是小票的条数
                    totalThreshold = checkList.size();
                    addTotal = totalThreshold + 1;
                    log.info("混凝土抗折强度【按车数】生成，当前车数：【{}】,需要添加车数：【{}】，最终车数：【{}】", totalThreshold, 1, addTotal);
                } else {
                    totalThreshold = checkList.stream().map(ExperimentCheckItemorder::getScQuantity).reduce((float) 0, Float::sum);
                    addTotal = totalThreshold + itemorder.getScquantity();
                    log.info("混凝土抗折【按重量】生成，当前重量：【{}】，小票生产方量：【{}】，最终方量：【{}】", totalThreshold, itemorder.getScquantity(), addTotal);
                }

                /**组装快检/批检与试验台账和小票的关系*/
                ExperimentCheckItemorder checkInfo = new ExperimentCheckItemorder().setItemorderId(itemorder.getItid())
                        .setTpz(tpz).setPhb(fPhbNo).setRwdh(String.valueOf(frwdh)).setGcmc(fGcmc)
                        .setCheckType(CheckEnum.BATCH.getCode()).setCreateTime(new Date())
                        .setTestCode(projectInfo.getTestCode()).setTestName(projectInfo.getTestName());

                log.info("判断是否清理试验委托和小票之间的关系表，最终方量：【{}】，阈值方量：【{}】", addTotal, checkThreshold);

                /**如果之前的加上本次的 大于阈值需要生产一个新的试验台账记录否则就用之前的*/
                if (addTotal >= Double.parseDouble(checkThreshold)) {// 如果大于阈值
                    log.info("如果之前的加上本次的大于阈值需要生产一个新的试验台账记录，开始清空experimentCheckItemorder表数据");
                    for (ExperimentCheckItemorder checkItemorderInfo : checkList) {
                        log.info("删除快检/批检与试验台账和小票的关系，对应对象：【{}】", JsonUtils.getJson(checkItemorderInfo));
                        experimentCheckItemorderMapper.deleteByPrimaryKey(checkItemorderInfo.getId());
                    }
                } else {
                    if (!checkList.isEmpty()) {
                        experimentId = checkList.get(0).getExperimentId();
                        log.info("试验委托和小票之间的关系表不为空，直接取第一条的试验委托，委托id：【{}】", experimentId);
                    } else {
                        log.info("试验委托和小票之间的关系表为空，需要重新生成试验委托！");
                    }
                }
                needAddCheckItemorderList.add(checkInfo);
            } else {
                log.info("混凝土抗折强度生成委托对应规则未知类型，类型：【{}】，任务单：【{}】，小票id：【{}】", checkRules, rwdextra.getFrwdh(), itemorder.getItid());
            }

            /**如果试验台账id为空 就需要生成一个新的  如果有就只要加对应的子表记录 共用之前的试验台账记录*/
            if (experimentId == null) {
                StringBuilder entrustExperiment = new StringBuilder();
                for (String entrustExperimentName : entrustExperimentSet) {
                    entrustExperiment.append(entrustExperimentName).append(",");
                }

                /**新增混凝土试验台账*/
                Experiment experiment = experimentService.getExperimentInfoByItemOrderInfo(itemorder, CheckEnum.BATCH.getCode(), entrustExperiment.deleteCharAt(entrustExperiment.length() - 1).toString(), testProjectCodeList);
                experiment.setPhb(fPhbNo);
                experiment.setFactory(itemorder.getMixtable());
                experiment.setConversionFactor(mesTpzToKz);
                /**组装物料相关信息*/
                this.payloadMaterialsInfo(itemorder.getTpz(), experiment);

                //experiment.setExperimentGist("GB/T 50081-2019");
                experiment.setCreateType(CreateTypeEnum.DEFAULT_CHECK.getCode()).setCreateCheckType(CheckTypeEnum.DEFAULT_CHECK.getCode());

                experimentMapper.insertSelective(experiment);

                experimentId = experiment.getId();

                /**生成对应试验台账详情信息*/
                if (!testProjectCodeList.isEmpty()) {
                    /**这里通过配合比号 查询mes的配合比信息*/
                    String lq = null;//龄期
                    MixProportion mixProportion = mixProportionMapper.selectByPhbNo(fPhbNo);
                    if (mixProportion != null) {
                        lq = mixProportion.getProportionLq();
                    }

                    List<ExperimentDetail> detailList = new ArrayList<>();
                    /**查询所有试验项目信息*/
                    for (TestProjectInfo testProjectInfo : testProjectInfoList) {
                        ExperimentDetail detail = new ExperimentDetail();
                        detail.setExperimentId(experiment.getId());
                        detail.setCheckType(CheckEnum.BATCH.getCode());
                        detail.setTestProjectCode(testProjectInfo.getTestCode());
                        detail.setTestProjectName(testProjectInfo.getTestName());
                        detail.setObjJson(testProjectInfo.getObjJson());

                        /**如果这里是混凝土抗折强度 并且对应mes的配合比龄期不为空  需要赋值龄期*/
                        if (testProjectInfo.getTestCode().equals(TestProjectEnum.CONCRETE_PARAM_KZQD.getCode()) && StringUtils.isNotBlank(lq)) {
                            ConcreteKzqd concreteKzqd = detail.getObjJson().toJavaObject(ConcreteKzqd.class);
                            concreteKzqd.setLq(lq);
                            detail.setObjJson(JsonUtils.beanToObject(concreteKzqd));
                        }
                        experimentDetailService.payloadOtherInfo(detail, testProjectInfo.getTestCode(), experiment.getExperimentType());
                        detailList.add(detail);
                    }
                    if (!detailList.isEmpty()) {
                        experimentDetailMapper.insertList(detailList);
                    }


                    /**如果是批检 并且在抽样试验项目配置中 有记录 直接生成对应的抽样记录 pk_experiment_sample_test_project*/
                    List<ExperimentSampleSmoke> sampleSmokeList = new ArrayList<>();
                    for (TestProjectInfo testProjectInfo : testProjectInfoList) {
                        /**这里一个试验项目一条记录*/
                        ExperimentSampleSmoke sampleSmoke = new ExperimentSampleSmoke();
                        sampleSmoke.setId(null);
                        sampleSmoke.erpInit(true);
                        sampleSmoke.setExperimentId(experiment.getId());
                        sampleSmoke.setSampleTime(new Date());
                        sampleSmoke.setIsTestBlock(0);// 是否是试块 1-是 0-不是
                        sampleSmoke.setSamplePersonName(experiment.getEntrustPersonName());
                        sampleSmoke.setDisposerPersonName(experiment.getEntrustPersonName());
                        sampleSmoke.setTestProjectCode(testProjectInfo.getTestCode());
                        sampleSmoke.setTestProjectName(testProjectInfo.getTestName());
                        sampleSmoke.setSampleUse(testProjectInfo.getTestName());
                        sampleSmokeList.add(sampleSmoke);
                    }
                    /**保存抽样信息*/
                    if (!sampleSmokeList.isEmpty()) {
                        experimentSampleSmokeMapper.insertList(sampleSmokeList);
                    }
                }
            }

            /**批检与试验台账和小票的关系*/
            for (ExperimentCheckItemorder checkItemorder : needAddCheckItemorderList) {
                /**这里赋值最新的试验委托id*/
                checkItemorder.setExperimentId(experimentId);
                experimentCheckItemorderMapper.insertSelective(checkItemorder);
            }

            /**插入试验台账对应小票数据和试验台账对应ERP任务单记录*/
            super.insertExperimentRelatedRecords(experimentId, itemorder.getItid(), rwdextra.getFrwdh());
            /**修改试验台账的代表数量*/
            super.updateExperimentBehalfNumber(experimentId);

            log.info("混凝土抗折强度生成完成！对应试验委托id：【{}】", experimentId);
            return experimentId;
        } catch (Exception e) {
            super.handleException("混凝土生成抗折强度失败", e);
            return null;
        }
    }
}
